/**
 * Created by arons on 16/6/30.
 */
'use strict';

/**
 * map
 */
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var mapArr = arr.map(String); // ['1', '2', '3', '4', '5', '6', '7', '8', '9']
console.log(mapArr);

function pow(x){
    "use strict";
    return x*x;
}

mapArr = arr.map(pow);
console.log(mapArr);

mapArr = arr.map(Object);
console.log(mapArr);

mapArr = arr.map((x)=>"A");
console.log(mapArr);

/**
 * reduce
 * Array的reduce()把一个函数作用在这个Array的[x1, x2, x3...]上，这个函数必须接收两个参数，
 * reduce()把结果继续和序列的下一个元素做累积计算，其效果就是：
 * [x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4)
 */
arr = [1, 3, 5, 7, 9];
var reduceArr = arr.reduce(function (x, y) {
    return x + y;
}); // 25
console.log('reduceArr result = ', reduceArr);


// reduce计算TODO完成的个数
arr = [{id:'1', completed:true},
    {id:'2', completed:false},
    {id:'3', completed:false},
    {id:'4', completed:true},
    {id:'5', completed:false}];
var completedCount = arr.reduce(((count, todo)=>todo.completed? count+1:count), 2);
console.log("completedCount count = ", completedCount);

function string2int(s) {
    //var arr = [];
    //for (var i = 0; i < s.length; i++) {
    //    arr.push(s[i] * 1);
    //}
    //var result = arr.reduce(function (x, y) {
    //    console.log("=====", x, y);
    //    return x * 10 + y;
    //});
    //return result;

    //var arr = s.split("").map((x)=>x*1);
    //console.log("string2int arr = ", arr);
    //var result = arr.reduce((x, y)=>x*10+y);
    //console.log("string2int result = ", result);
    //return result;

    //return s.split("").map((x)=>x*1).reduce((x, y)=>x*10+y);

    //return s*1;

    return +s;
}

// 测试:
if (string2int('0') === 0 && string2int('12345') === 12345 && string2int('12300') === 12300) {
    if (string2int.toString().indexOf('parseInt') !== -1) {
        console.log('请勿使用parseInt()!');
    } else if (string2int.toString().indexOf('Number') !== -1) {
        console.log('请勿使用Number()!');
    } else {
        console.log('测试通过!');
    }
}
else {
    console.log('测试失败!');
}



function normalize(arr) {
    return arr.map((x)=> x.slice(0, 1).toUpperCase() + x.slice(1).toLocaleLowerCase());
}

// 测试:
if (normalize(['adam', 'LISA', 'barT']).toString() === ['Adam', 'Lisa', 'Bart'].toString()) {
    console.log('测试通过!');
}
else {
    console.log('测试失败!');
}

/**
 * Filter
 */
arr = [1, 2, 4, 5, 6, 9, 10, 15];
var filterArr = arr.filter(function (x) {
    return x % 2 !== 0;
});
console.log("filterArr = "+filterArr);


arr = ['A', '', 'B', null, undefined, 'C', '  ', ,];
filterArr = arr.filter(function (s) {
    return s && s.trim(); // 注意：IE9以下的版本没有trim()方法
});
console.log("filterArr = "+filterArr);


function get_primes(arr) {
    return arr.filter(function (x){
        if(x === 1) return false;
        if(x === 2) return true;
        for(var i=2; i<x; i++){
            if(x%i === 0){
                return false;
            }
        }
        return true;
    });
}

// 测试:
var
    x,
    r,
    arr = [];
for (x = 1; x < 100; x++) {
    arr.push(x);
}
r = get_primes(arr);
if (r.toString() === [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97].toString()) {
    console.log('测试通过!');
} else {
    console.log('测试失败: ' + r.toString());
}

/**
 * Sort
 */
console.log("Test Sort");
arr = [10, 20, 20, 1, 1, 2];
var cpyArr = arr.map(x=>x);
var sortArr = arr.sort((x, y)=>x>y);
console.log(sortArr);
console.log(cpyArr);

// Test 闭包
/**
 * 相关参数和变量都保存在返回的函数中，这种称为“闭包（Closure）
 * @param initial
 * @returns {{inc: Function}}
 */
function create_counter(initial) {
    var x = initial || 0;
    return {
        inc: function () {
            x += 1;
            return x;
        }
    }
}
var c1 = create_counter();
var counterResult = c1.inc(); // 1
console.log(counterResult);
counterResult = c1.inc(); // 2
console.log(counterResult);
counterResult = c1.inc(); // 3
console.log(counterResult);


function count() {
    var arr = [];
    for (var i=1; i<=3; i++) {
        arr.push((function (n) {
            return function () {
                return n * n;
            }
        })(i));
    }
    return arr;
}

var results = count();
var f1 = results[0];
var f2 = results[1];
var f3 = results[2];

var fResult = f1(); // 1
console.log(fResult);
fResult = f2(); // 4
console.log(fResult);
fResult = f3(); // 9
console.log(fResult);

/**
 * 创建一个匿名函数并且立即执行的语法
 */
var f = (function (n) {
    return function () {
        return n * n;
    }
})(5);
console.log(f());

function pown(n){
    return function (x) {
        return Math.pow(x, n);
    }
}

var pow2 = pown(2);
var pow3 = pown(3);

console.log('pow2(2) = '+pow2(2));
console.log('pow3(3) = '+pow3(3));

/**
 * 箭头函数
 * 箭头函数完全修复了this的指向，this总是指向词法作用域，也就是外层调用者obj：
 */

var obj = {
    birth: 1990,
    getAge: function () {
        var b = this.birth; // 1990
        var fn = () => {
            return new Date().getFullYear() - this.birth; // this指向obj对象
        }
        return fn();
    }
};
var objAge = obj.getAge(); // 25
console.log(objAge);


var obj2 = {
    birth: 1990,
    getAge: function (year) {
        var b = this.birth; // 1990
        var fn = (y) => y - this.birth; // this.birth仍是1990
        return fn.call({birth:2000}, year);
    }
};
objAge = obj2.getAge(2015); // 25
console.log(objAge);

/**
 * 在对象中使用箭头函数和使用普通函数对照
 * @type {{birth: number, getAge: Function}}
 */
var obj3 = {
    birth: 1990,
    getAge: function () {
        var b = this.birth; // 1990
        var fn = function(){
            return new Date().getFullYear() - this.birth;
        }
        return fn.call({birth: 2000});
    }
};
objAge = obj3.getAge(2015); // 25
console.log(objAge);


function* fib(max) {
    var
        t,
        a = 0,
        b = 1,
        n = 1;
    while (n < max) {
        yield a;
        t = a + b;
        a = b;
        b = t;
        n ++;
    }
     return a;
}

var len = 10;
var f = fib(len);
for(var i = 0;i<len+1; i++){
    console.log("f.next() = ", f.next());
}